package com.xb.system.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.xb.model.domain.DistinctUsersInfo;
import com.xb.model.domain.UsersInfo;
import com.xb.model.req.RequestDto;
import com.xb.model.sout.UsersInfoExportModel;
import com.xb.system.mapper.DistinctUsersInfoMapper;
import com.xb.system.mapper.UsersInfoMapper;
import com.xb.system.service.UserInfoQueryService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author lzy
 * @create 2024/11/11 12:42
 */
@Service
public class UserInfoQueryServiceImpl implements UserInfoQueryService {
    @Autowired
    private UsersInfoMapper usersInfoMapper;

    @Autowired
    private DistinctUsersInfoMapper distinctUsersInfoMapper;

    private static final int BATCH_SIZE = 100000; // 每个文件的最大数据量

    /**
     * 根据请求条件查询并生成 Excel
     *
     * @param requestDto 查询条件
     * @param outputFilePath 输出文件路径
     * @return Excel 文件路径
     */
    @Override
    public List<String> queryAndGenerateExcel(RequestDto requestDto, String outputFilePath) {
        List<String> generatedFiles = new ArrayList<>();
        ExcelWriter excelWriter = null;
        WriteSheet writeSheet = null;

        // 确保 outputFilePath 是文件夹路径，如果是文件夹，则给定一个默认的文件名
        if (!outputFilePath.endsWith(File.separator)) {
            outputFilePath += File.separator;
        }

        // 获取查询条件（例如州或城市）
        String queryCriteria = getQueryCriteriaString(requestDto);

        int fileCount = 0;  // 用于文件的计数
        String fileName = outputFilePath  + queryCriteria + "_" + fileCount + "_" + System.currentTimeMillis()  +  ".xlsx";  // 生成文件名

        try {
            // 查询所有数据
            List<UsersInfoExportModel> allData = queryData(requestDto);

            // 创建 ExcelWriter
            excelWriter = EasyExcel.write(fileName, UsersInfoExportModel.class).build();
            writeSheet = EasyExcel.writerSheet("Sheet1").build();

            int totalDataSize = allData.size();
            int currentBatchStart = 0;

            while (currentBatchStart < totalDataSize) {
                // 计算当前批次的结束位置
                int currentBatchEnd = Math.min(currentBatchStart + BATCH_SIZE, totalDataSize);
                List<UsersInfoExportModel> currentBatchData = allData.subList(currentBatchStart, currentBatchEnd);

                // 写入当前批次数据
                excelWriter.write(currentBatchData, writeSheet);

                // 更新文件计数，并生成新的文件名
                fileCount++;
                String newFileName = outputFilePath +queryCriteria+ "_" + fileCount + "_" + System.currentTimeMillis()  + ".xlsx";
                generatedFiles.add(newFileName);

                // 如果当前批次没有达到总数据量，就继续写入到新的文件
                if (currentBatchEnd < totalDataSize) {
                    excelWriter.finish();  // 完成当前文件的写入
                    excelWriter = EasyExcel.write(newFileName, UsersInfoExportModel.class).build();  // 创建新的 ExcelWriter
                    writeSheet = EasyExcel.writerSheet("Sheet1").build();  // 创建新的 Sheet
                }

                currentBatchStart = currentBatchEnd;  // 更新批次起始位置
            }

            return generatedFiles;

        } finally {
            if (excelWriter != null) {
                excelWriter.finish(); // 关闭 ExcelWriter
            }
        }
    }

    /**
     * 获取查询条件字符串（例如：NEW YORK，或者其他条件）
     * 用于在文件名中使用
     *
     * @param requestDto 查询条件对象
     * @return 查询条件字符串
     */
    private String getQueryCriteriaString(RequestDto requestDto) {
        // 可以根据实际的查询条件选择合适的字段
        StringBuilder queryCriteria = new StringBuilder();

        if (StringUtils.isNotBlank(requestDto.getCompanyCity())) {
            queryCriteria.append(requestDto.getCompanyCity().toUpperCase()).append("_");
        }
        if (StringUtils.isNotBlank(requestDto.getCompanyAddress())) {
            queryCriteria.append(requestDto.getCompanyAddress().toUpperCase()).append("_");
        }
        if (StringUtils.isNotBlank(requestDto.getPrimaryIndustry())) {
            queryCriteria.append(requestDto.getPrimaryIndustry().toUpperCase()).append("_");
        }
        if (StringUtils.isNotBlank(requestDto.getCompanyIndustry())) {
            queryCriteria.append(requestDto.getCompanyIndustry().toUpperCase()).append("_");
        }
        if (StringUtils.isNotBlank(requestDto.getCompanyState())) {
            queryCriteria.append(requestDto.getCompanyState().toUpperCase()).append("_");
        }

        // 如果有其他查询条件可以在这里继续扩展

        if (queryCriteria.length() > 0) {
            // 去除结尾多余的 "_"
            queryCriteria.setLength(queryCriteria.length() - 1);
        } else {
            queryCriteria.append("ALL"); // 默认处理没有查询条件的情况
        }

        return queryCriteria.toString();
    }

    /**
     * 根据条件查询数据
     *
     * @param requestDto 查询条件
     * @return 查询结果
     */
    private List<UsersInfoExportModel> queryData(RequestDto requestDto) {
        List<UsersInfoExportModel> exportModels = new ArrayList<>();

        // 构建查询参数
        Map<String, Object> params = new HashMap<>();
        if (StringUtils.isNotBlank(requestDto.getPrimaryIndustry())) {
            params.put("primaryIndustry", requestDto.getPrimaryIndustry());
        }
        if (StringUtils.isNotBlank(requestDto.getCompanyIndustry())) {
            params.put("companyIndustry", requestDto.getCompanyIndustry());
        }
        if (StringUtils.isNotBlank(requestDto.getCompanyAddress())) {
            params.put("companyAddress", requestDto.getCompanyAddress());
        }
        if (StringUtils.isNotBlank(requestDto.getCompanyCity())) {
            params.put("companyCity", requestDto.getCompanyCity());
        }
        if (StringUtils.isNotBlank(requestDto.getCompanyState())) {
            params.put("companyState", requestDto.getCompanyState());
        }

        // 查询 users_info 表
        List<UsersInfo> usersInfoList = usersInfoMapper.selectList(params);

        // 如果 users_info 为空，查询 distinct_users_info 表
        if (usersInfoList.isEmpty()) {
            List<DistinctUsersInfo> distinctUsersInfoList = distinctUsersInfoMapper.selectList(params);

            // 转换为 UsersInfoExportModel 并返回
            exportModels = distinctUsersInfoList.stream()
                    .map(this::convertToExportModel)
                    .collect(Collectors.toList());
        } else {
            // 转换为 UsersInfoExportModel 并返回
            exportModels = usersInfoList.stream()
                    .map(this::convertToExportModel)
                    .collect(Collectors.toList());
        }

        return exportModels;
    }

    // 转换方法保持不变
    private UsersInfoExportModel convertToExportModel(UsersInfo usersInfo) {
        UsersInfoExportModel model = new UsersInfoExportModel();
        model.setFirstName(usersInfo.getFirstName());
        model.setLastName(usersInfo.getLastName());
        model.setBusinessEmail(usersInfo.getBusinessEmail());
        model.setJobTitle(usersInfo.getJobTitle());
        model.setSeniorityLevel(usersInfo.getSeniorityLevel());
        model.setDepartment(usersInfo.getDepartment());
        model.setMobilePhone(usersInfo.getMobilePhone());
        model.setLinkedinUrl(usersInfo.getLinkedinUrl());
        model.setCompanyName(usersInfo.getCompanyName());
        model.setCompanyDomain(usersInfo.getCompanyDomain());
        model.setCompanyLinkedinUrl(usersInfo.getCompanyLinkedinUrl());
        return model;
    }

    private UsersInfoExportModel convertToExportModel(DistinctUsersInfo distinctUsersInfo) {
        UsersInfoExportModel model = new UsersInfoExportModel();
        model.setFirstName(distinctUsersInfo.getFirstName());
        model.setLastName(distinctUsersInfo.getLastName());
        model.setBusinessEmail(distinctUsersInfo.getBusinessEmail());
        model.setJobTitle(distinctUsersInfo.getJobTitle());
        model.setSeniorityLevel(distinctUsersInfo.getSeniorityLevel());
        model.setDepartment(distinctUsersInfo.getDepartment());
        model.setMobilePhone(distinctUsersInfo.getMobilePhone());
        model.setLinkedinUrl(distinctUsersInfo.getLinkedinUrl());
        model.setCompanyName(distinctUsersInfo.getCompanyName());
        model.setCompanyDomain(distinctUsersInfo.getCompanyDomain());
        model.setCompanyLinkedinUrl(distinctUsersInfo.getCompanyLinkedinUrl());
        return model;
    }
}

